#!/usr/bin/env python
#
# Copyright 2008 Richard J. Bell. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

""" Wikify classes for geo wiki site. """

# Python Imports
import re

# Google App Engine Imports

# Application Imports

#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
# Wikify a wiki page's contents.
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------

def wikify( wiki_body ):
    """ Apply wiki transforms to wiki_body and return for display.

    Parameters: str, wiki_body - the non-wikified wiki contents
    Returns: str: Contents wikified.
    """
    transforms = [
        InternalLinks(),
        AutoLink(),
        #WikiWords(),
        #HideReferers(),
    ]
    for transform in transforms:
        wiki_body = transform.run(wiki_body)
    return wiki_body

class Transform(object):
    """ Abstraction for a regular expression transform.
      Transform subclasses have two properties:

      regexp: the regular expression defining what will be replaced
      replace(MatchObject): returns a string replacement for a regexp
                            match

      We iterate over all matches for that regular expression, calling
        replace() on the match to determine what text should replace the
        matched text.

      The Transform class is more expressive than regular expression
        replacement because the replace() method can execute arbitrary code
        to, e.g., look up a WikiWord to see if the page exists before
        determining if the WikiWord should be a link.
    """
    def run(self, content):
        """ Runs this transform over the given content.
        Parameters: content: str, The data to apply a transformation to.
        Returns: str, Data after transformation is applied.
        """
        parts = []
        offset = 0
        for match in self.regexp.finditer(content):
            parts.append(content[offset:match.start(0)])
            parts.append(self.replace(match))
            offset = match.end(0)
        parts.append(content[offset:])
        return ''.join(parts)
    
class InternalLinks( Transform ):
    """ Generate internal links for text. """
    def __init__( self ):
        self.regexp = re.compile( '\[\[(.*?)\]\]', re.S+re.M )
    def replace( self, match ):
        strs = match.group(1).split('|')
        ww = strs[0].strip()
        if len(strs) > 1:
            tt = strs[1].strip()
        else:
            tt = ww
        return '<a class="wikiword" href="/%s">%s</a>' % (ww, tt)
    
class AutoLink(Transform):
    """ Generate links for URL text. """
    def __init__(self):
        self.regexp = re.compile(
            r'([^"])\b((http|https)://[^ \t\n\r<>\(\)&"]+' \
            r'[^ \t\n\r<>\(\)&"\.])')
    def replace(self, match):
        url = match.group(2)
        return match.group(1) + \
               '<a href="%s">%s</a>' % (url, url)
    
class WikiWords(Transform):
    """ Translates WikiWords to links.
    Look up all the WikiWords (ie. camel case words) and link those that
    have current wiki pages.
    """
    def __init__(self):
        self.regexp = re.compile(r'[A-Z][a-z]+([A-Z][a-z]+)+')
    def replace(self, match):
        wikiword = match.group(0)
        if WikiPage.exists(wikiword):
            return '<a class="wikiword" href="/%s">%s</a>' % (wikiword, wikiword)
        else:
            return wikiword

class AutoLink(Transform):
    """ Generate links for URL text, ex. http://www.google.com. """
    def __init__(self):
        self.regexp = re.compile(
            r'([^"])\b((http|https)://[^ \t\n\r<>\(\)&"]+' \
            r'[^ \t\n\r<>\(\)&"\.])')
    def replace(self, match):
        url = match.group(2)
        return match.group(1) + \
               '<a class="autourl" href="%s">%s</a>' % (url, url)

class HideReferers(Transform):
    """A transform that hides referers for external hyperlinks."""
    def __init__(self):
        self.regexp = re.compile(r'href="(http[^"]+)"')
    def replace(self, match):
        url = match.group(1)
        scheme, host, path, parameters, query, fragment = urlparse.urlparse(url)
        url = 'http://www.google.com/url?sa=D&amp;q=' + urllib.quote(url)
        return 'href="%s"' % (url,)
    
